#include "glbase/glflat.h"

#define STATUS_READY 0
#define STATUS_WORK 1
#define STATUS_ERROR 2

CSTR statusNames[]={_T("Ready"),_T("Working..."),_T("Error!")};

int shift=5,start=0,end=0,count_calc=0,cluster=0,status=0;
double t=0,s=0,dev=1,beta=0.1,sample=1,R_estim,ratio=0.1,ratio_calc;
GraphData *target;

class GMPLoad:public FlatApplication
{
	Font fontSmall;
	FlatText tbDev,tbBeta,tbSample,tbShift,tbStart,tbEnd,tbRatio,tbTarget;
	FlatLabel lDev,lBeta,lSample,lShift,lStart,lEnd,lRatio,lTarget;
	FlatButton bApply, bReset, bLoad, bFull, bExit, bSampling;
	FlatGraph fgProcess,fgCorrel;
	GaussMarkov gmp_estim,gmp_accum;
	SignalStat mBeta,mDev,varR;
	void reset()
	{
		mBeta.clear();
		mDev.clear();
		varR.clear();
	}
	void getValues()
	{
		shift=format.toInt(tbShift.text);
		start=format.toInt(tbStart.text);
		end=format.toInt(tbEnd.text);
		dev=format.toDouble(tbDev.text);
		beta=format.toDouble(tbBeta.text);
		sample=format.toDouble(tbSample.text);
		ratio=format.toDouble(tbRatio.text);
		target=fgProcess.graph.getChannel(tbTarget.text);
	}
	void setValues()
	{
		tbShift.text=format.toString(shift);
		tbStart.text=format.toString(start);
		tbEnd.text=format.toString(end);
		tbDev.text=format.toString(gmp_estim.stdev);
		tbBeta.text=format.toString(gmp_estim.beta);
		tbSample.text=format.toString(sample);
		tbRatio.text=format.toString(ratio);
	}
	void apply();
	BOOL load();

	BOOL create();
	void update();
	void draw2D();
	BOOL glCreate();
	void glDestroy();
	BOOL listen(WORD id, WORD code, const void *info);
	
} gmp;
void GMPLoad::apply()
{
	status=STATUS_ERROR;
	if(!target||start==end||!shift||!dev)
		return;
	int index,length;
	index=fgProcess.graph.selectIndex();
	length=fgProcess.graph.selectLength();
	if(!length)
	{
		index=0;
		length=-1;
	}
	t=s=0;
	if(!gmp_estim.init(target->data,shift,sample,index,length))
		return;
	fgCorrel.graph.setMarkers(gmp_estim.R,gmp_estim.t_R,shift,8,INT_BLACK);
	mBeta.add(gmp_estim.beta);
	mDev.add(gmp_estim.stdev);
	varR.add(gmp_estim.R[shift-1]);
	ratio_calc=sqrt(varR.var())/dev;
	//gmp_accum.init(mDev.mean(),mBeta.mean(),sample);
	count_calc=gmp_accum.getSamples(ratio);
	fgCorrel.graph.clear();
	for(int i=0;i<shift;i++)
	{
		R_estim=gmp_estim.autocorrel(s);
		//R_accum=gmp_accum.autocorrel(s);
		fgCorrel.graph.addPoint();
		s+=sample;
	}
	fgCorrel.graph.update();
	status=STATUS_READY;
}
BOOL GMPLoad::load()
{
	FILE *file=fd.readFile();
	if(!file)
		return FALSE;
	cluster=0;
	fgProcess.graph.load(file,TRUE,bSampling.checked);
	fgProcess.graph.hideAll();
	fgProcess.build();
	tbStart.text=_T("0");
	tbEnd.text=format.toString(fgProcess.graph.getPointCount());
	fd.closeFile();
	return TRUE;
}
BOOL GMPLoad::listen(WORD id, WORD code, const void *info)
{
	if(	id==bApply.id||
		id==tbBeta.id||
		id==tbSample.id||
		id==tbShift.id||
		id==tbDev.id||
		id==tbStart.id||
		id==tbEnd.id||
		id==tbRatio.id)
	{
        if(code==FLAT_ACTION_DEFAULT)
		{
			HCURSOR oldCursor=setCursor(IDC_WAIT);
			getValues();
			if(bReset.checked)
				reset();
			apply();
			setValues();
			SetCursor(oldCursor);
			return TRUE;
		}
	}
    else if(id==bLoad.id)
	{
		if(code==FLAT_ACTION_DEFAULT)
		{
			fd.open();
			load();
			return TRUE;
		}
	}
	else if(id==bExit.id)
	{
		if(code==FLAT_ACTION_DEFAULT)
		{
			terminate();
			return TRUE;
		}
	}
	else if(id==fgProcess.id)
	{
		if(code==FLAT_ACTION_DEFAULT)
		{
			double start,end;
			start=fgProcess.graph.selectStart;
			end=fgProcess.graph.selectEnd;
			if(start!=end)
				tbStart.text=format.toString(start);
			else
				tbStart.text=_T("0");
			tbEnd.text=format.toString(end);
			return TRUE;
		}
		else if(code==FLAT_ACTION_SELECT)
		{
			GraphData *tmp=(GraphData *)info;
			tbTarget.text=tmp->getName();
			return TRUE;
		}
	}
	else if(id==fgCorrel.id)
	{
		if(code==FLAT_ACTION_DEFAULT)
		{
			double ratio=fgCorrel.graphScroll.getRatio();
			tbShift.text=format.toString(round(ratio*(shift-1)+1));
			return TRUE;
		}
	}
	else if(id==bFull.id)
	{
		toggleFullscreen();
		return TRUE;
	}
	return FALSE;
}
BOOL GMPLoad::create ()	
{
	FlatApplication::create();
	name=_T("Gauss-Markov Process Observer");

	display.width=1024;
	display.height=768;

	format.precision=3;

	fontSmall.name=_T("Courier New");
	fontSmall.height=-12;

	fd.addFilter(_T("dat"),_T("Matlab Data File"));
	fd.addFilter(_T("*"),_T("All Files"));

	fgProcess.bgColor=INT_GRAY;
	fgProcess.graph.nGridX=3;
	fgProcess.graph.nGridY=5;
	fgProcess.graph.margin=10;
	fgProcess.graph.marginChannel.set(15,60);
	fgProcess.graph.font=&fontSmall;
	fgProcess.graph.formatX.precision=2;
	fgProcess.graph.formatY.precision=2;
	fgProcess.channelRead=15;
	fgProcess.setBounds(540,30,460,640);
	fgProcess.margin.set(5,5);
	fgProcess.fontColor=INT_BLACK;
	fgProcess.format.precision=6;

	fgCorrel.copy(fgProcess);
	fgCorrel.graph.marginChannel.set(15,50);
	fgCorrel.channelRead=3;
	fgCorrel.stick(DIR_LEFT,-10,300,&fgProcess);
	fgCorrel.size.set(500,340);

	lDev.text=_T("Stddev:");
	lDev.fontColor=INT_WGRAY;
	lDev.margin.set(5,1);
	lDev.stick(DIR_LEFT,-10,0,&tbDev);
	lDev.adjustSize=TRUE;

	lBeta.text=_T("Beta:");
	lBeta.copy(lDev);
	lBeta.stick(DIR_DOWN,0,5);

	lSample.text=_T("Sample:");
	lSample.copy(lBeta);
	lSample.stick(DIR_DOWN,0,5);

	lShift.text=_T("Shift:");
	lShift.copy(lBeta);
	lShift.stick(DIR_DOWN,0,5);

	lStart.text=_T("Start:");
	lStart.copy(lBeta);
	lStart.stick(DIR_DOWN,0,5);

	lEnd.text=_T("End:");
	lEnd.copy(lBeta);
	lEnd.stick(DIR_DOWN,0,5);

	lRatio.text=_T("Ratio:");
	lRatio.copy(lBeta);
	lRatio.stick(DIR_DOWN,0,5);

	lTarget.text=_T("Target:");
	lTarget.copy(lBeta);
	lTarget.stick(DIR_DOWN,0,5);

	bLoad.text=_T("Load");
	bLoad.symbol='l';
	bLoad.borderLine=1;
	bLoad.borderColor=INT_GRAY;
	bLoad.activeLine=2;
	bLoad.font=&font;
	bLoad.fontColor=INT_BLACK;
	bLoad.margin.set(20,3);
	bLoad.bgColor=0xFFDDDDDD;
	bLoad.overColor=INT_WHITE;
	bLoad.pressColor=INT_YELLOW;
	bLoad.stick(DIR_RIGHT,10,0,&tbDev);
	bLoad.adjustSize=TRUE;

	bApply.text=_T("Apply");
	bApply.copy(bLoad);
	bApply.symbol='a';
	bApply.stick(DIR_DOWN,0,5,&bLoad);

	bReset.text=_T("Reset");
	bReset.copy(bLoad);
	bReset.margin.set(10,3);
	bReset.checkable=TRUE;
	bReset.checked=TRUE;
	bReset.pressColor=INT_CYAN;
	bReset.stick(DIR_DOWN,0,5);

	bSampling.text=_T("Sampl");
	bSampling.copy(bReset);
	bSampling.checked=TRUE;
	bSampling.stick(DIR_DOWN,0,5);

	bFull.text=_T("Fullscr");
	bFull.symbol='f';
	bFull.copy(bReset);
	bFull.checked(createFullScreen);
	bFull.stick(DIR_DOWN,0,5);

	bExit.text=_T("Exit");
	bExit.copy(bLoad);
	bExit.pressColor=INT_WRED;
	bExit.stick(DIR_DOWN,0,5);

	tbDev.borderLine=1;
	tbDev.borderColor=INT_WGRAY;
	tbDev.activeLine=2;
	tbDev.font=&font;
	tbDev.fontColor=INT_BLACK;
	tbDev.margin.set(2,1);
	tbDev.setBounds(100,40,70,0);

	tbBeta.copy(tbDev);
	tbBeta.stick(DIR_DOWN,0,5);

	tbSample.copy(tbBeta);
	tbSample.stick(DIR_DOWN,0,5);

	tbRatio.copy(tbBeta);
	tbRatio.stick(DIR_DOWN,0,5);

	tbShift.copy(tbBeta);
	tbShift.size.x=50;
	tbShift.stick(DIR_DOWN,0,5);

	tbStart.copy(tbShift);
	tbStart.size.x+=20;
	tbStart.stick(DIR_DOWN,0,5);

	tbEnd.copy(tbShift);
	tbEnd.size.x+=20;
	tbEnd.stick(DIR_DOWN,0,5);

	tbTarget.copy(tbShift);
	tbTarget.size.x+=100;
	tbTarget.stick(DIR_DOWN,0,5);

	fgCorrel.graph.add( _T("shift"),INT_WHITE,0,&s);
	fgCorrel.graph.add( _T("R estim"),INT_RED,1,&R_estim);

	add(&fgProcess);
	add(&fgCorrel);

	add(&lDev);
	add(&lBeta);
	add(&lSample);
	add(&lRatio);
	add(&lShift);
	add(&lStart);
	add(&lEnd);
	add(&lTarget);

	add(&bLoad);
	add(&bApply);
	add(&bReset);
	add(&bSampling);
	add(&bFull);
	add(&bExit);

	add(&tbDev);
	add(&tbBeta);
	add(&tbSample);
	add(&tbRatio);
	add(&tbShift);
	add(&tbStart);
	add(&tbEnd);
	add(&tbTarget);

	return TRUE;
}
BOOL GMPLoad::glCreate ()
{
	fontSmall.create(window.hDC);
	FlatApplication::glCreate();
	setValues();
	//ShowWindow(window.hWnd, SW_MAXIMIZE); 
	return TRUE;												
}
void GMPLoad::glDestroy()
{
	FlatApplication::glDestroy();
	fontSmall.destroy();
}
void GMPLoad::update()
{
	/*if(accum>0)
	{
		accum--;
		if(!accum)
		{
			tbAccum.text=format.toString(accum0);
			tbCount.text=format.toString(count_calc);
		}
		else
		{
			tbAccum.text=format.toString(accum);
		}
		apply();
		updated=TRUE;
	}*/
}
void GMPLoad::draw2D()
{
	font.color=INT_WHITE;
	font.x=10;
	font.y=20;
	glPrint(&font,name);
	
	font.color=INT_GREEN;
	font.x=280;
	font.y+=18;
	glPrint(&font,_T("status:       %s"), statusNames[status]);
	font.color=INT_WGRAY;
	font.y+=18;
	glPrint(&font,_T("used scan:    %d"), gmp_estim.realScan);
	font.color=INT_WHITE;
	font.y+=18;
	glPrint(&font,_T("estim count:  %d"), count_calc);
	font.color=INT_MAGENTA;
	font.y+=18;
	glPrint(&font,_T("calc ratio:   %.3f"), ratio_calc);
	font.y+=18;
	if(ratio<ratio_calc)
	{
		font.color=INT_RED;
		glPrint(&font,_T("              BAD"));
	}
	else
	{
		font.color=INT_GREEN;
		glPrint(&font,_T("              OK"));
	}
}

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	return gmp.main(hInstance,hPrevInstance,lpCmdLine,nCmdShow);
}